package com.alpesressources.comexpert;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import net.sf.jasperreports.engine.JasperPrint;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import com.alpesressources.comexpert.bo.IObject;
import com.alpesressources.comexpert.bo.request.ReportRequest;
import com.alpesressources.comexpert.bo.response.ErrorResponse;
import com.alpesressources.comexpert.bo.response.ReportResponse;
import com.alpesressources.comexpert.bo.response.Response;
import com.alpesressources.comexpert.bo.response.ErrorResponse.EnumErrorCode;
import com.alpesressources.comexpert.bo.response.ResponseObject.EnumResult;
import com.alpesressources.comexpert.jasper.Jasper;
import com.alpesressources.comexpert.util.MyJsonSerializer;

public class Report extends AAction {

	private static Logger logger = Logger.getLogger(Report.class);

	@Override
	public void processGet(ServletConfig config,
			HashMap<String, Object> queryString, HttpServletResponse response)
			throws ServletException, IOException {
	}

	@Override
	public void processPost(ServletConfig config,
			HashMap<String, Object> queryString, IObject postRequest,
			HttpServletResponse response) throws ServletException, IOException {

		ReportRequest reportRequest = (ReportRequest) postRequest;

		ReportResponse reportResponse = new ReportResponse();

		if (reportRequest.getReportName() != null
				&& reportRequest.getRender() != null
				&& reportRequest.getReportParams() != null) {

			Context initContext;
			DataSource ds;

			try {
				initContext = new InitialContext();
				ds = (DataSource) initContext
						.lookup("java:comp/env/jdbc/coMexpertReports");

				Connection conn = ds.getConnection();
				PreparedStatement stmt = conn.prepareStatement("use "
						+ queryString.get("dossier"));
				stmt.execute();
				stmt.close();

				String reportFullPath;
				String reportsPath;

				reportsPath = config.getServletContext().getInitParameter(
						"reportsPath");

				reportFullPath = reportsPath + "/" + queryString.get("dossier")
						+ "/" + reportRequest.getReportName();

				logger.debug("Try to compile: " + reportFullPath);

				Jasper jasper = new Jasper();

				if (jasper.compileReport(reportFullPath)) {
					JasperPrint jasperPrint;
					if ((jasperPrint = jasper.fillReport(reportFullPath
							+ ".jasper",
							convertParams(reportRequest.getReportParams()),
							conn)) != null) {
						ByteArrayOutputStream buffer = null;
						Base64 base64 = new Base64();

						if (reportRequest.getRender().equalsIgnoreCase("pdf")) {
							buffer = jasper.exportPDFReport(jasperPrint);

							reportResponse.setResult(EnumResult.OK);
							reportResponse.setContentType("application/pdf");
							reportResponse.setSize(buffer.size());
							reportResponse.setContent(base64
									.encodeToString(buffer.toByteArray()));

							buffer.close();
						} else if (reportRequest.getRender().equalsIgnoreCase(
								"txt")) {
							buffer = jasper.exportTXTReport(jasperPrint);

							reportResponse.setResult(EnumResult.OK);
							reportResponse.setContentType("text/plain");
							reportResponse.setSize(buffer.size());
							reportResponse.setContent(base64
									.encodeToString(buffer.toByteArray()));

							buffer.close();
						} else {
							reportResponse.setResult(EnumResult.NOK);

							logger.error("Unable to fill report as "
									+ reportRequest.getRender());
						}
					} else {
						reportResponse.setResult(EnumResult.NOK);

						logger.error("Unable to fill report");
					}
				} else {
					reportResponse.setResult(EnumResult.NOK);

					logger.info("Unable to compile report");
				}

			} catch (NamingException e) {
				reportResponse.setResult(EnumResult.NOK);

				logger.error("Report failed", e);
			} catch (SQLException e) {
				reportResponse.setResult(EnumResult.NOK);

				logger.error("Report failed", e);
			}
		} else {
			reportResponse.setResult(EnumResult.NOK);

			logger.info("Report failed: all required fields are not present in the request");
		}

		Response r = new Response();
		ErrorResponse errorResponse = new ErrorResponse();

		errorResponse.setErrorCode(EnumErrorCode.NO_ERROR);
		r.setErrorResponse(errorResponse);

		r.getData().add(reportResponse);

		MyJsonSerializer myJsonSerializer = new MyJsonSerializer();

		response.getOutputStream().write(
				myJsonSerializer.serialize(r).getBytes());
	}

	public Class<?> getObjectClass() {
		return ReportRequest.class;
	}

	private Map<String, Object> convertParams(Map<String, String> params) {
		Map<String, Object> ret = new HashMap<String, Object>();
		for (Entry<String, String> e : params.entrySet()) {
			ret.put(e.getKey(), e.getValue());
		}

		return ret;
	}

}
